home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
DEMON
/
RISCOS2
/
TCP_131S.ARC
/
c
/
tcpcmd
< prev
next >
Wrap
Text File
|
1994-01-08
|
10KB
|
362 lines
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "global.h"
#include "timer.h"
#include "mbuf.h"
#include "netuser.h"
#include "internet.h"
#include "tcp.h"
#include "cmdparse.h"
#include "misc.h"
#include "arc.h"
#include "asy.h"
#include "os.h"
#include "swis.h"
static int dotcpreset(int, char **);
static int dohangup(int, char **);
static int doirtt(int, char **);
static int dortt(int, char **);
static int dotcpkick(int, char **);
static int domss(int, char **);
static int dowindow(int, char **);
static int dotcpstat(int, char **);
static int tstat(void);
static void state_tcp(struct tcb *);
/* TCP connection states */
char *tcpstates[] = {
"Closed",
"Listen",
"SYN sent",
"SYN received",
"Established",
"FIN wait 1",
"FIN wait 2",
"Close wait",
"Closing",
"Last ACK",
"Time wait"
};
/* TCP closing reasons */
char *reasons[] = {
"Normal",
"Reset",
"Timeout",
"ICMP"
};
static struct timer busy;
static int busy_checks = 0;
static int busy_limit = 0;
static BOOL busy_exit = FALSE;
/* TCP subcommand table */
struct cmds tcpcmds[] = {
"hangup", dohangup, 3, "tcp hangup <check> <after> [exit]", NULLCHAR,
"irtt", doirtt, 0, NULLCHAR, NULLCHAR,
"kick", dotcpkick, 2, "tcp kick <tcb>", NULLCHAR,
"mss", domss, 0, NULLCHAR, NULLCHAR,
"reset", dotcpreset, 2, "tcp reset <tcb>", NULLCHAR,
"rtt", dortt, 3, "tcp rtt <tcb> <val>", NULLCHAR,
"status", dotcpstat, 0, NULLCHAR, NULLCHAR,
"window", dowindow, 0, NULLCHAR, NULLCHAR,
NULLCHAR,
};
int dotcp(int argc, char **argv)
{
return subcmd(tcpcmds,argc,argv);
}
/* Eliminate a TCP connection */
static int dotcpreset(int argc, char **argv)
{
register struct tcb *tcb;
extern char notval[];
argc = argc;
tcb = (struct tcb *)htol(argv[1]);
if(!tcpval(tcb)){
cwprintf(NULL, notval);
return 1;
}
close_self(tcb,RESET);
return 0;
}
static void dotcpbusy(void *p)
{
register int i;
register struct tcb *tcb;
p = p;
start_timer(&busy);
for (i = 0; i < NTCB; i++)
{
for (tcb = tcbs[i]; tcb != NULLTCB; tcb = tcb->next)
{
if (tcb->state > 3)
{
busy_checks = 0;
return;
}
}
}
busy_checks++;
if (asy_scan())
cwprintf(NULL, "TCP checks clear = %d Hanging up after %d more\r\n", busy_checks, busy_limit - busy_checks);
else
busy_checks = 0;
if (busy_checks == busy_limit)
{
iostop();
if (busy_exit)
net_exit();
}
}
static int dohangup(int argc, char **argv)
{
busy.func = dotcpbusy;
busy.arg = NULL;
busy_checks = 0;
busy_limit = atoi(argv[2]);
cwprintf(NULL, "Check every %s seconds, hangup after %s clear checks\r\n", argv[1], argv[2]);
if (argc == 4 && strnicmp(argv[3], "exit", MIN(strlen(argv[3]), 4)) == 0)
{
busy_exit = TRUE;
cwprintf(NULL, "and exit program.\r\n");
}
if (busy_limit > 0)
{
set_timer(&busy, atol(argv[1]) * 1000L);
start_timer(&busy);
}
else
{
stop_timer(&busy);
}
return(0);
}
/* Set initial round trip time for new connections */
static int doirtt(int argc, char **argv)
{
if(argc < 2)
cwprintf(NULL, "%lu\r\n",tcp_irtt);
else
tcp_irtt = atol(argv[1]);
return 0;
}
/* Set smoothed round trip time for specified TCB */
static int dortt(int argc, char **argv)
{
register struct tcb *tcb;
extern char notval[];
argc = argc;
tcb = (struct tcb *)htol(argv[1]);
if(!tcpval(tcb)){
cwprintf(NULL, notval);
return 1;
}
tcb->srtt = atol(argv[2]);
return 0;
}
/* Force a retransmission */
static int dotcpkick(int argc, char **argv)
{
register struct tcb *tcb;
extern char notval[];
argc = argc;
tcb = (struct tcb *)htol(argv[1]);
if(kick_tcp(tcb) == -1){
cwprintf(NULL, notval);
return 1;
}
return 0;
}
/* Set default maximum segment size */
static int domss(int argc, char **argv)
{
if(argc < 2)
cwprintf(NULL, "%u\r\n",tcp_mss);
else
tcp_mss = atoi(argv[1]);
return 0;
}
/* Set default window size */
static int dowindow(int argc, char **argv)
{
if(argc < 2)
cwprintf(NULL, "%u\r\n",tcp_window);
else
tcp_window = atoi(argv[1]);
return 0;
}
/* Display status of TCBs */
static int dotcpstat(int argc, char **argv)
{
register struct tcb *tcb;
extern char notval[];
if(argc < 2){
tstat();
} else {
tcb = (struct tcb *)htol(argv[1]);
if(tcpval(tcb))
state_tcp(tcb);
else
cwprintf(NULL, notval);
}
return 0;
}
/* Dump TCP stats and summary of all TCBs
* &TCB Rcv-Q Snd-Q Local socket Remote socket State
* 1234 0 0 xxx.xxx.xxx.xxx:xxxxx xxx.xxx.xxx.xxx:xxxxx Established
*/
static int tstat(void)
{
register int i;
register struct tcb *tcb;
cwprintf(NULL, "conout %u conin %u reset out %u runt %u chksum err %u bdcsts %u\r\n",
tcp_stat.conout,tcp_stat.conin,tcp_stat.resets,tcp_stat.runt,
tcp_stat.checksum,tcp_stat.bdcsts);
cwprintf(NULL, " &TCB Rcv-Q Snd-Q Local socket Remote socket State\r\n");
for(i=0;i<NTCB;i++){
for(tcb=tcbs[i];tcb != NULLTCB;tcb = tcb->next){
cwprintf(NULL, "%8lx%6u%6u ",(long)tcb,tcb->rcvcnt,tcb->sndcnt);
cwprintf(NULL, "%-23s",psocket(&tcb->conn.local));
cwprintf(NULL, "%-23s",psocket(&tcb->conn.remote));
cwprintf(NULL, "%-s",tcpstates[tcb->state]);
if(tcb->state == LISTEN && (tcb->flags & CLONE))
cwprintf(NULL, " (S)");
cwprintf(NULL, "\r\n");
}
}
return 0;
}
/* Dump a TCP control block in detail */
static void state_tcp(struct tcb *tcb)
{
int32 sent,recvd;
if(tcb == NULLTCB)
return;
/* Compute total data sent and received; take out SYN and FIN */
sent = tcb->snd.una - tcb->iss; /* Acknowledged data only */
recvd = tcb->rcv.nxt - tcb->irs;
switch(tcb->state){
case LISTEN:
case SYN_SENT: /* Nothing received or acked yet */
sent = recvd = 0;
break;
case SYN_RECEIVED:
recvd--; /* Got SYN, no data acked yet */
sent = 0;
break;
case ESTABLISHED: /* Got and sent SYN */
case FINWAIT1: /* FIN not acked yet */
sent--;
recvd--;
break;
case FINWAIT2: /* Our SYN and FIN both acked */
sent -= 2;
recvd--;
break;
case CLOSE_WAIT: /* Got SYN and FIN, our FIN not yet acked */
case CLOSING:
case LAST_ACK:
sent--;
recvd -= 2;
break;
case TIME_WAIT: /* Sent and received SYN/FIN, all acked */
sent -= 2;
recvd -= 2;
break;
}
cwprintf(NULL, "Local: %s",psocket(&tcb->conn.local));
cwprintf(NULL, " Remote: %s",psocket(&tcb->conn.remote));
cwprintf(NULL, " State: %s\r\n",tcpstates[tcb->state]);
cwprintf(NULL, " Init seq Unack Next Resent CWind Thrsh Wind MSS Queue Total\r\n");
cwprintf(NULL, "Send:");
cwprintf(NULL, "%9lx",tcb->iss);
cwprintf(NULL, "%9lx",tcb->snd.una);
cwprintf(NULL, "%9lx",tcb->snd.nxt);
cwprintf(NULL, "%7lu",tcb->resent);
cwprintf(NULL, "%6u",tcb->cwind);
cwprintf(NULL, "%6u",tcb->ssthresh);
cwprintf(NULL, "%6u",tcb->snd.wnd);
cwprintf(NULL, "%5u",tcb->mss);
cwprintf(NULL, "%6u",tcb->sndcnt);
cwprintf(NULL, "%11lu\r\n",sent);
cwprintf(NULL, "Recv:");
cwprintf(NULL, "%9lx",tcb->irs);
cwprintf(NULL, " ");
cwprintf(NULL, "%9lx",tcb->rcv.nxt);
cwprintf(NULL, "%7lu",tcb->rerecv);
cwprintf(NULL, " ");
cwprintf(NULL, " ");
cwprintf(NULL, "%6u",tcb->rcv.wnd);
cwprintf(NULL, " ");
cwprintf(NULL, "%6u",tcb->rcvcnt);
cwprintf(NULL, "%11lu\r\n",recvd);
if(tcb->reseq != (struct reseq *)NULL){
register struct reseq *rp;
cwprintf(NULL, "Reassembly queue:\r\n");
for(rp = tcb->reseq;rp != (struct reseq *)NULL; rp = rp->next){
cwprintf(NULL, " seq x%lx %u bytes\r\n",rp->seg.seq,rp->length);
}
}
if(tcb->backoff > 0)
cwprintf(NULL, "Backoff %u ",tcb->backoff);
if(tcb->flags & RETRAN)
cwprintf(NULL, "Retrying ");
switch(tcb->timer.state){
case TIMER_STOP:
cwprintf(NULL, "Timer stopped ");
break;
case TIMER_RUN:
cwprintf(NULL, "Timer running (%ld/%ld ms) ",
(long)MSPTICK * (tcb->timer.start - tcb->timer.count),
(long)MSPTICK * tcb->timer.start);
break;
case TIMER_EXPIRE:
cwprintf(NULL, "Timer expired ");
}
cwprintf(NULL, "SRTT %ld ms Mean dev %ld ms\r\n",tcb->srtt,tcb->mdev);
}
int rem_kick(void)
{
register int i;
register struct tcb *tcb;
for(i=0;i<NTCB;i++){
for(tcb=tcbs[i];tcb != NULLTCB;tcb = tcb->next){
kick_tcp(tcb);
}
}
return 0;
}